package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.CourseComment;
import com.wzcl.app.dao.model.UserCourse;
import com.wzcl.app.dao.repository.AppUserRepository;
import com.wzcl.app.dao.repository.CourseCommentRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.dto.CourseCommentDto;
import com.wzcl.app.service.CourseCommentService;
import com.wzcl.app.service.UserCourseService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

@Log4j2
@Service
public class CourseCommentServiceImpl implements CourseCommentService {

    @Resource
    private CourseCommentRepository repository;

    @Resource
    private UserCourseService userCourseService;

    @Resource
    private AppUserRepository appUserRepository;

    @Override
    public CourseComment addCourseComment(CourseCommentDto courseCommentDto) {
        List<UserCourse> list = userCourseService.findByPhoneAndCourseId(courseCommentDto.getUserPhone(), courseCommentDto.getCourseId());
        // TODO 评论bug !list.isEmpty()
        if (list.isEmpty()) {
            throw new BusinessException(CodeMsg.USER_COURSE_NOT_EXIST);
        }
        if (courseCommentDto.getParentId() != null) {
            CourseComment parentComment = getAndCheckById(courseCommentDto);
            //课程校验
            if (!parentComment.getCourseId().equals(courseCommentDto.getCourseId())) {
                throw new BusinessException(CodeMsg.COURSE_COMMENT_OPERATE_FAIL, "回复评论课程不符合");
            }
        }
        CourseComment courseComment = new CourseComment();
        BeanUtils.copyProperties(courseCommentDto, courseComment);
        courseComment.setUserId(courseCommentDto.getUserId());
        return repository.save(courseComment);
    }

    @Override
    public CourseComment delCourseComment(CourseCommentDto courseCommentDto) {
        CourseComment comment = getAndCheckById(courseCommentDto);
        //校验操作人
        if (!comment.getUserPhone().equals(courseCommentDto.getUserPhone())) {
            throw new BusinessException(CodeMsg.USER_NOT_MATCH);
        }
        
        log.info("CourseComment:{} Physical deletion", JSON.toJSONString(comment));
        repository.delete(comment);
        return comment;
    }

    @Override
    public CourseComment getCourseCommentById(Integer id) {
        return repository.findById(id).orElse(null);
    }

    @Override
    public CourseComment getCourseCommentTreeById(Integer id) {
        //校验
        CourseComment comment = getAndCheckById(id);
        //填充评论数据
        putCourseCommentTree(comment);
        return comment;
    }


    @Override
    public CourseComment getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少评论Id");
        }
        CourseComment comment = getCourseCommentById(id);
        if (comment == null) {
            throw new BusinessException(CodeMsg.COURSE_COMMENT_NOT_EXIST);
        }
        return comment;
    }

    public void putCourseCommentTree(CourseComment comment) {
        List<CourseComment> commentList = repository.findAllByParentId(comment.getId());
        if (commentList != null && commentList.size() > 0) {
            for (CourseComment courseComment : commentList) {
                putCourseCommentTree(courseComment);
            }
            comment.setCommentList(commentList);
        }
    }

    @Override
    public MyPage<CourseComment> getCourseCommentPage(CourseCommentDto courseCommentDto) {
        return new MyPage<>(repository.findAll(getSpecification(courseCommentDto), courseCommentDto.getPageable()));
    }

    private Specification<CourseComment> getSpecification(CourseCommentDto courseCommentDto) {
        return new Specification<CourseComment>() {
            @Override
            public Predicate toPredicate(Root<CourseComment> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (courseCommentDto.getParentId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("parentId"), courseCommentDto.getParentId()));
                } else {
                    predicates.add(criteriaBuilder.isNull(root.get("parentId")));
                }
                if (courseCommentDto.getCourseId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("courseId"), courseCommentDto.getCourseId()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
}
